/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.tom.social.watcher.agent.behaviour;

import jade.core.AID;
import jade.core.behaviours.CyclicBehaviour;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.domain.FIPAException;
import jade.lang.acl.ACLMessage;
import jade.util.leap.Iterator;
import java.util.List;
import java.util.Random;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import pl.tom.social.common.jade.TaskBarProxy;
import pl.tom.social.common.types.ConversationIDType;
import pl.tom.social.dal.SocialDatabaseFacade;
import pl.tom.social.dal.entity.Site;
import pl.tom.social.dal.entity.SiteLink;
import pl.tom.social.watcher.jade.LocalJade;

/**
 *
 * @author Tom
 */
public class WatcherBehaviour extends CyclicBehaviour {

	private static final Logger logger = Logger.getLogger(WatcherBehaviour.class);
	private TaskBarProxy taskBar;
	private String server;

	public WatcherBehaviour(TaskBarProxy taskBar) {
		this.taskBar = taskBar;
	}

	public WatcherBehaviour(TaskBarProxy taskBar, String server) {
		this.taskBar = taskBar;
		this.server = server;
	}

	@Override
	public void action() {
		SocialDatabaseFacade db = new SocialDatabaseFacade();
		if (server == null) {
			this.updateAction(db);
		} else {
			this.searchAction(db);
		}
	}

	private void searchAction(SocialDatabaseFacade db) {
		List<SiteLink> list = db.getLikeServerSiteLink(server);
		for (SiteLink link : list) {
			String url = link.getUrl();
			taskBar.update(url);
			try {
				if (db.getSite(url) == null) {
					notifyFetcher(url);
				}
			} catch (Exception ex) {
				logger.log(Level.ERROR, ex);
			}
		}
	}

	private void updateAction(SocialDatabaseFacade db) {
		Site site = db.getSiteForUpdate();
		taskBar.update("Trying " + site.getUrl());
		notifyFetcher(site.getUrl());
	}

	private void notifyFetcher(String url) {
		try {
			String serviceType = "fetcherAdmin";
			DFAgentDescription[] results = LocalJade.getServices(myAgent, serviceType);
			logger.log(Level.INFO, results.length + " services found.");
			if (results.length == 0) {
				NotifyDescriptor nf = new NotifyDescriptor.Message("No fetcher service found",
					NotifyDescriptor.WARNING_MESSAGE);
				DialogDisplayer.getDefault().notifyLater(nf);
				myAgent.doDelete();
			}
			for (int i = 0; i < results.length; ++i) {
				DFAgentDescription dfd = results[i];
				if (proposeTask(dfd, serviceType, url)) {
					return;
				}
			}
		} catch (FIPAException ex) {
			logger.log(Level.ERROR, ex);
		}
	}

	private boolean proposeTask(DFAgentDescription dfd, String serviceType, String url) {
		AID provider = dfd.getName();
		Iterator it = dfd.getAllServices();
		while (it.hasNext()) {
			ServiceDescription sd = (ServiceDescription) it.next();
			if (sd.getType().equals(serviceType)) {
				for (int j = 0; j < 5; j++) {
					ACLMessage msg = new ACLMessage(ACLMessage.PROPOSE);
					msg.setConversationId(ConversationIDType.AddNewNode.name());
					msg.setContent(url);
					msg.addReceiver(provider);
					myAgent.send(msg);
					logger.log(Level.DEBUG, "Message send to " + provider.getName() + ", content:" + msg.getContent());
					msg = myAgent.blockingReceive(5000);
					if (msg != null) {
						if (msg.getPerformative() == ACLMessage.ACCEPT_PROPOSAL) {
							logger.log(Level.INFO, "Task accepted by " + msg.getSender().getName());
							return true;
						} else {
							logger.log(Level.INFO, "Task rejected by " + msg.getSender().getName());
							taskBar.update("All fetcher agents busy. Waiting...");
							Random rand = new Random();
							myAgent.doWait((rand.nextInt(9) + 1) * 30000);
						}
					}
				}
			}
		}
		return false;
	}
}
